﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System;

namespace Xceed.Silverlight.Data
{
  internal class GroupEnumerator : AsyncParentEnumerator<DataPath>
  {
    #region Static Fields

    private static readonly Guid JumpMoveAndFetchCallId = DataUtils.CreateCallId();

    #endregion

    #region Constructor

    internal GroupEnumerator( IAsyncEnumerator<DataPath> childEnumerator, IContextualGroupDataHelper groupHelper )
      : base( null )
    {
      GroupLevelEnumerator groupLevelEnumerator = new GroupLevelEnumerator( childEnumerator, groupHelper );
      GroupMoveEnumerator groupMoveEnumerator = new GroupMoveEnumerator( groupLevelEnumerator );
      GroupContextEnumerator groupStatEnumerator = new GroupContextEnumerator( groupMoveEnumerator, groupHelper );

      this.ChildEnumerator = groupStatEnumerator;
    }

    #endregion

    #region CachedPathProvider Internal Property

    internal Func<DataSourceContext, DataPath, DataPath> CachedPathProvider
    {
      get
      {
        return this.LevelEnumerator.CachedPathProvider;
      }

      set
      {
        this.LevelEnumerator.CachedPathProvider = value;
      }
    }

    #endregion

    #region ContextEnumerator Private Property

    private GroupContextEnumerator ContextEnumerator
    {
      get
      {
        return ( GroupContextEnumerator )this.ChildEnumeratorTyped;
      }
    }

    #endregion

    #region MoveEnumerator Private Property

    private GroupMoveEnumerator MoveEnumerator
    {
      get
      {
        return ( GroupMoveEnumerator )this.ContextEnumerator.ChildEnumeratorTyped;
      }
    }

    #endregion

    #region LevelEnumerator Private Property

    private GroupLevelEnumerator LevelEnumerator
    {
      get
      {
        return ( GroupLevelEnumerator )this.MoveEnumerator.ChildEnumerator;
      }
    }

    #endregion

    #region GroupMoveEnumerator Nested Type

    private class GroupMoveEnumerator : MoveConverterEnumerator<DataPath>, IGroupEnumerator
    {
      internal GroupMoveEnumerator( GroupLevelEnumerator childEnumerator )
        : base( childEnumerator )
      {
      }

      private GroupLevelEnumerator GroupLevelEnumerator
      {
        get
        {
          return ( GroupLevelEnumerator )this.ChildEnumerator;
        }
      }

      protected override bool ConvertMoveForRequest( JumpMoveAndFetchParameters parameters )
      {
        //If the move is approximate, do not fetch it, pass the call directly to the child enumerator.
        //If no modifications are made to the content, move will be precise anyway.
        return ( parameters.ExpectedMoveCount != 0 )
            && ( !parameters.ApproximateMove )
            && ( GroupLevelEnumerator.AddOrRemoveItems( parameters.Context.GroupContext ) );
      }

      public IAsyncResult BeginGroupItemCount( DataSourceContext context, DataPath groupPath, AsyncCallback userCallback, object asyncState )
      {
        return this.GroupLevelEnumerator.BeginGroupItemCount( context, groupPath, userCallback, asyncState );
      }

      public EstimateInt64 EndGroupItemCount( IAsyncResult asyncResult )
      {
        return this.GroupLevelEnumerator.EndGroupItemCount( asyncResult );
      }

      #region IGroupEnumerator Members

      public IAsyncResult BeginGetBaseItems( JumpMoveAndFetchParameters parameters, AsyncCallback userCallback, object asyncState )
      {
        return this.GroupLevelEnumerator.BeginGetBaseItems( parameters, userCallback, asyncState );
      }

      public JumpMoveAndFetchResult<DataPath> EndGetBaseItems( JumpMoveAndFetchAsyncResult jumpMoveAndFetchAsyncResult )
      {
        return this.GroupLevelEnumerator.EndGetBaseItems( jumpMoveAndFetchAsyncResult );
      }

      #endregion
    }

    #endregion
  }
}
